package org.jeecg.modules.operations.assistant.wechat.controller;

import cn.hutool.http.HttpUtil;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.operations.assistant.vehicle.util.ApiServiceUtil;
import org.jeecg.modules.operations.assistant.work.entity.CustomerInfo;
import org.jeecg.modules.operations.assistant.work.service.ICustomerInfoService;
import org.jeecg.modules.system.controller.CommonController;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysThirdAccount;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.model.ThirdLoginModel;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysDictService;
import org.jeecg.modules.system.service.ISysThirdAccountService;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* @Description: 微信登录
* @Author: jeecg-boot
* @Date:   2024-06-06
* @Version: V1.0
*/
@Api(tags="微信登录")
@RestController
@RequestMapping("/sys/thirdLogin")
@Slf4j
public class WeChatLoginController extends JeecgController<CustomerInfo, ICustomerInfoService> {
   @Autowired
   private ICustomerInfoService customerInfoService;

    @Value("${justauth.type.WECHAT_MINI_PROGRAM.client-id:}")
    private String weChatClientId;
    @Value("${justauth.type.WECHAT_MINI_PROGRAM.client-secret:}")
    private String weChatClientSecret;
    @Autowired
    private ISysThirdAccountService sysThirdAccountService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private ISysDictService sysDictService;

    @Resource
    private BaseCommonService baseCommonService;

    @Autowired
    private ISysDepartService sysDepartService;

    @Resource
    CommonController commonController;

    @Autowired
    private RestTemplate restTemplate;

   /**
    * 通过id查询
    *
    * @param code
    * @return
    */
   //@AutoLog(value = "客户信息-通过id查询")
//   @ApiOperation(value="客户信息-通过id查询", notes="客户信息-通过id查询")
   @GetMapping(value = "/loginByWeChat")
   public Result<JSONObject> loginByWeChat(@RequestParam(name="code",required=true) String code) {
//       CustomerInfo customerInfo = customerInfoService.getById(id);
       String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+weChatClientId+"&secret="+weChatClientSecret+"&js_code="+code+"&grant_type=authorization_code";

       String res = ApiServiceUtil.get(url);
       JSONObject resultData = JSONObject.parseObject(res);
//{"session_key":"b2eJkO1CtzctegtobJmfig==","expires_in":7200,"openid":"oEXge0RAvSOOwP0M47msBuLH7ii0","unionid":"olz5z6a5tTnJwSTnh0o_BWwc6pJI"}

       String source = "wechat_open";
       String uuid = resultData.getString("unionid");
       Result<JSONObject> result = new Result<JSONObject>();
       if(oConvertUtils.isNotEmpty(uuid)) {
//           JSONObject v = result.getJSONObject("version");
//           this.version = v.getString("number"); const openid = res.data.openid;
//           return Result.error("未找到对应数据");
           //判断有没有这个人
           //update-begin-author:wangshuai date:20201118 for:修改成查询第三方账户表
           LambdaQueryWrapper<SysThirdAccount> query = new LambdaQueryWrapper<SysThirdAccount>();
           query.eq(SysThirdAccount::getThirdType, source);
           //update-begin---author:wangshuai---date:2023-10-07---for:【QQYUN-6667】敲敲云，线上解绑重新绑定一直提示这个---
           query.eq(SysThirdAccount::getTenantId, CommonConstant.TENANT_ID_DEFAULT_VALUE);
           //update-end---author:wangshuai---date:2023-10-07---for:【QQYUN-6667】敲敲云，线上解绑重新绑定一直提示这个---
           query.and(q -> q.eq(SysThirdAccount::getThirdUserUuid, uuid).or().eq(SysThirdAccount::getThirdUserId, uuid));
           List<SysThirdAccount> thridList = sysThirdAccountService.list(query);
           SysThirdAccount user = null;
           if(thridList==null || thridList.size()==0) {
               result.setCode(60003);
               result.setResult(resultData);
               result.setMessage("未注册");
               return result;
           }else {
               //已存在 只设置用户名 不设置头像
               user = thridList.get(0);
           }
           // 生成token
           //update-begin-author:wangshuai date:20201118 for:从第三方登录查询是否存在用户id，不存在绑定手机号
           if(oConvertUtils.isNotEmpty(user.getSysUserId())) {
               String sysUserId = user.getSysUserId();
               SysUser sysUser = sysUserService.getById(sysUserId);
               String token = saveToken(sysUser);
               result.setMessage("登录成功");
               return Result.ok(token);
//               modelMap.addAttribute("token", token);
           }else{
//               modelMap.addAttribute("token", "绑定手机号,"+""+uuid);
               result.setCode(60004);
               result.setResult(resultData);
               result.setMessage("绑定手机号");
               return result;
           }
           //update-end-author:wangshuai date:20201118 for:从第三方登录查询是否存在用户id，不存在绑定手机号
           //update-begin--Author:wangshuai  Date:20200729 for：接口在签名校验失败时返回失败的标识码 issues#1441--------------------
       } else {
           result.setMessage("登录失败");
//           return Result.ok("token=登录失败,");
           return result;
       }
   }


    private String saveToken(SysUser user) {
        // 生成token
        String token = JwtUtil.sign(user.getUsername(), user.getPassword());
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        // 设置超时时间
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
        return token;
    }

    /**
     * 登录失败超出次数5 返回true
     * @param username
     * @return
     */
    private boolean isLoginFailOvertimes(String username){
        String key = CommonConstant.LOGIN_FAIL + username;
        Object failTime = redisUtil.get(key);
        if(failTime!=null){
            Integer val = Integer.parseInt(failTime.toString());
            if(val>5){
                return true;
            }
        }
        return false;
    }

    /**
     * 获取手机号接口
     *
     * @param jsonObject
     * @return
     */
    @ApiOperation("获取手机号接口")
    @PostMapping("/getPhoneNumber")
    public Result<JSONObject> getPhoneNumber(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        Result<JSONObject> result = new Result<JSONObject>();
        String code = jsonObject.getString("code");
//        weChatClientId+"&secret="+weChatClientSecret
        String appId = weChatClientId; // 小程序APPID
        String appSecret = weChatClientSecret; // 小程序密钥

//        if (StringUtils.isEmpty(code)) {
//            return AjaxResult.error("手机号获取凭证不能为空！");
//        }
        //通过appid和secret来获取token
        String tokenUrl = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, appSecret);
        String accessToken = String.valueOf(JSON.parseObject(HttpUtil.get(tokenUrl)).get("access_token"));
        log.info(accessToken);

        //通过token和code来获取用户手机号
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken + "&code=" + code;

        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("code", code);
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(paramMap, headers);
        ResponseEntity<Object> response = restTemplate.postForEntity(url, httpEntity, Object.class);
        String body = String.valueOf(response.getBody());// 解析JSON字符串
        log.info(body);
        // 定义一个正则表达式来匹配 phoneNumber
        Pattern pattern = Pattern.compile("phoneNumber=(\\d+)");
        Matcher matcher = pattern.matcher(body);
        if (matcher.find()) {
            String phoneNumber = matcher.group(1); // 获取括号中的数字
            log.info("phoneNumber:" + phoneNumber);
            return result.success(phoneNumber);
        } else {
            return result.error("手机号获取失败！");
        }

//        String result = null;
//        try {
//            String url = "https://api.weixin.qq.com/cgi-bin/token?" +
//                    "grant_type=client_credential&appid={0}&secret={1}";
//            String replaceUrl = url.replace("{0}", appid)
//
//                    .replace("{1}", secret);
//            String res = HttpUtil.get(replaceUrl);
//            JSONObject json_token = JSON.parseObject(res);
//            String access_token = json_token.getString("access_token");
//            String urlTwo = "https://api.weixin.qq.co" +
//                    "m/wxa/business/getuserphonenumber?access_token={0}";
//            String replaceUrlTwo = urlTwo.replace("{0}", access_token);
//            Map<String, Object> requestParam = new HashMap<>();
//            // 手机号调用凭证
//            requestParam.put("code", code);
//            String jsonStr = JSON.toJSONString(requestParam);
//            HttpResponse response = HttpRequest.post(replaceUrlTwo)
//                    .header(Header.CONTENT_ENCODING, "UTF-8")
//                    // 发送json数据需要设置contentType
//                    .header(Header.CONTENT_TYPE,
//                            "application/x-www-form-urlencoded")
//                    .body(jsonStr)
//                    .execute();
//
//            if (response.getStatus() == HttpStatus.HTTP_OK) {
//
//                result = response.body();
//
//            }
//
//            System.out.println(response.body() );
//
//        } catch (HttpException e) {
//
//            e.printStackTrace();
//
//        }
//
//        return JSONObject.parseObject(result).get("phone_info");


//        String accessToken = jsonObject.getString("accessToken");
//        String urlTwo = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+access_token+"&code="+code;

//        String resTwo = ApiServiceUtil.get(urlTwo);
//        ApiServiceUtil.
//        JSONObject resultData = JSONObject.parseObject(resTwo);
        //update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
//        if (isLoginFailOvertimes(phone)) {
//            return result.error500("该用户登录失败次数过多，请于10分钟后再次登录！");
//        }
//        result.setResult(resultData);
//        result.success("登录成功");
//        return result;
    }

    /**
     * 第三方绑定手机号返回token
     *
     * @param jsonObject
     * @return
     */
    @ApiOperation("手机号登录接口")
    @PostMapping("/bindingPhone")
    @ResponseBody
    public Result<String> bindingPhone(@RequestBody JSONObject jsonObject) {
        Result<String> result = new Result<String>();
        String phone = jsonObject.getString("mobile");
        String thirdUserUuid = jsonObject.getString("thirdUserUuid");
        // 校验验证码
        String realname = jsonObject.getString("realname");
        String source = "wechat_open";
        String username = realname;

        String avatar = jsonObject.getString("avatarUrl");

        //构造第三方登录信息存储对象
        ThirdLoginModel tlm = new ThirdLoginModel(source, thirdUserUuid, username, avatar);
        sysThirdAccountService.saveThirdUser(tlm,CommonConstant.TENANT_ID_DEFAULT_VALUE);
        //update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
        String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+phone;
        Object captchaCache = redisUtil.get(redisKey);
        //update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
		/*if (oConvertUtils.isEmpty(captcha) || !captcha.equals(captchaCache)) {
			result.setMessage("验证码错误");
			result.setSuccess(false);
			return result;
		}*/
        //校验用户有效性
        SysUser sysUser = sysUserService.getUserByPhone(phone);
        if(sysUser != null){
            // 存在用户，直接绑定
            sysThirdAccountService.updateThirdUserId(sysUser,thirdUserUuid);
        }else{
            // 不存在手机号，创建用户
            sysUser = sysThirdAccountService.createUser(phone,thirdUserUuid,CommonConstant.TENANT_ID_DEFAULT_VALUE);
        }
        sysUser = sysUserService.getUserByPhone(phone);
        String salt = oConvertUtils.randomGen(8);
        sysUser.setSalt(salt);
        sysUser.setUsername(phone);
        String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), "123456", salt);
        sysUser.setPassword(passwordEncode);
        this.sysUserService.updateById(sysUser);

        String token = saveToken(sysUser);
        result.setSuccess(true);
        result.setResult(token);
        return result;
    }

    /**
     * 文件上传统一方法
     * @param request
     * @param response
     * @return
     */
    @PostMapping(value = "/upload")
    public Result<?> upload(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return commonController.upload(request,response);
    }

    /**
     * 获取手机号接口
     *
     * @return
     */
    @ApiOperation("获取手机号接口")
    @GetMapping("/getOpenId")
    public void getOpenId(String code, String state, String orderId, HttpServletResponse response) throws IOException {
        Result<JSONObject> result = new Result<JSONObject>();
        log.info("获取微信响应的参数code:{}，state：{}，orderId：{}",code,state,orderId);
        // 1、获取 登陆凭证code
        if (StringUtils.isEmpty(code)) {
//            return result.error("code获取失败！");
//            return "code获取失败！";
        }

//        String code = jsonObject.getString("code");
//        weChatClientId+"&secret="+weChatClientSecret
//        String appId = "wx23bf3224159631e6"; // 小程序APPID
        String appId = "wx23bf3224159631e6";
        String appSecret = "307083070d24b3fb7fffd7399bdfad25"; // 小程序密钥


//        if (StringUtils.isEmpty(code)) {
//            return AjaxResult.error("手机号获取凭证不能为空！");
//        }
        //通过appid和secret来获取token
        String tokenUrl = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, appSecret);
//        String accessToken = String.valueOf(JSON.parseObject(HttpUtil.get(tokenUrl)).get("access_token"));
//        log.info(accessToken);
//        return result.success(accessToken);
//        //通过token和code来获取用户手机号
        String url = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", appId, appSecret,code);
        log.info("url==={}",url);
        JSONObject data = JSON.parseObject(HttpUtil.get(url));
        log.info("data==={}",data);
        // 重定向到另一个路径或者外部URL
        String redirectUrl = "/wechatpay/index.html?openId="+data.getString("openid")+"#/pages/wechatpay/wechatpay";
        response.sendRedirect(redirectUrl);
    }

//    服务端通过code 获取accessToken、openid和unionid
//    https://api.weixin.qq.com/sns/oauth2/access_token

//    再通过开放平台 使用openid拉取用户信息
//    https://api.weixin.qq.com/sns/userinfo?access_token=

    @RequestMapping("mpLogin")
    public String mpLogin(String code, String state, HttpServletResponse response) throws IOException {
        log.info("获取微信响应的参数code:{}，state：{}",code,state);
        // 1、获取 登陆凭证code
        if (StringUtils.isEmpty(code)) {
            return "code获取失败！";
        }

        // 2、通过code 获取accessToken、openid和unionid
//        String resData = null;
//        try {
//            resData = wechatUtil.mpOauth2(code);
//        } catch (IOException e) {
//            log.error("mpOauth2",e);
//            return "获取openid失败！";
//        }
//
//        HashMap<String, String> sessionData = JsonUtil.toObj(resData, HashMap.class);
//        log.info("H5登陆sessionData：" + sessionData);
//
//        String mpOpenid = sessionData.get("openid");
//        String unionId = sessionData.get("unionid");
//
//        // 解析响应结果
//        if (null == sessionData || StringUtils.isEmpty(mpOpenid)) {
//            return "解析openid失败！";
//        }
//
//        // 3、拉取用户信息
//        JSONObject wxUser = wechatUtil.getMpUserInfo(sessionData.get("access_token"),mpOpenid);
//        String avatar = wxUser.getString("headimgurl");
//        String nickname = wxUser.getString("nickname");
//
//        String loginIp = IpUtils.getIpAddr(request);
//        // 静默注册
//        UserInfo userInfo = userInfoService.silenceRegister(unionId,loginIp,"",mpOpenid,avatar,nickname);
//
//        log.info("公众号方式登录-账号绑定,静默注册完成:{}",userInfo.getId());
//
//        // 绑定成功提示
////    response.sendRedirect("https://mp.weixin.qq.com/s/IU1-K2sixLsjscWy1sM7yw");
//
//        // 使用微信头像和昵称成功提示
//        response.sendRedirect("https://mp.weixin.qq.com/s/zykJLau9cSC8uR3g7zJFlg");
        return "";
    }

    @RequestMapping(value = "/auth")
    @ResponseBody
    public void auth6(HttpServletRequest request,
                      HttpServletResponse response){
        log.info("auth checking start...");
        try {
            String nonce = request.getParameter("nonce");
            String timestamp = request.getParameter("timestamp");
            String signature = request.getParameter("signature");
            String echoStr = request.getParameter("echostr");
            String code = request.getParameter("code");
            log.info("auth,nonce:{},timestamp:{},signature:{},echoStr:{},code:{}",nonce,timestamp,signature,echoStr,code);
            response.setContentType("text/html");
            response.getWriter().print(echoStr);
            log.info("auth echoStr:"+echoStr);
            log.info("auth checking success!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @PostMapping(value = "/555auth")
    @ResponseBody
    public void auth7(HttpServletRequest request,
                      HttpServletResponse response){
        log.info("auth checking start...");
        try {
            String nonce = request.getParameter("nonce");
            String timestamp = request.getParameter("timestamp");
            String signature = request.getParameter("signature");
            String echoStr = request.getParameter("echostr");
            String code = request.getParameter("code");
            log.info("auth,nonce:{},timestamp:{},signature:{},echoStr:{},code:{}",nonce,timestamp,signature,echoStr,code);
            response.setContentType("text/html");
            response.getWriter().print(echoStr);
            log.info("auth echoStr:"+echoStr);
            log.info("auth checking success!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}